package org.javaboy.fmall.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Joiner;
import org.javaboy.fmall.entity.FmBase;
import org.javaboy.fmall.entity.FmItem;
import org.javaboy.fmall.entity.KeyType;
import org.javaboy.fmall.entity.TableDate;
import org.javaboy.fmall.mapper.FmBaseMapper;
import org.javaboy.fmall.mapper.FmItemMapper;
import org.javaboy.fmall.service.FmBaseService;
import org.javaboy.fmall.utils.generateTool.DataForTypeEnum;
import org.javaboy.fmall.utils.generateTool.RandomUtil;
import org.javaboy.fmall.utils.returnTool.BusinessException;
import org.javaboy.fmall.utils.returnTool.ColeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
//import org.springframework.util.StringUtils;
import org.apache.commons.lang.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (FmBase)表服务实现类
 *
 * @author makejava
 * @since 2020-07-16 01:25:11
 */
@Service
public class FmBaseServiceImpl implements FmBaseService {
    @Resource
    private FmBaseMapper fmBaseDao;
    @Autowired
    private FmItemMapper fmItemMapper;


    /**
     * 通过ID查询单条数据
     *
     * @param 主键
     * @return 实例对象
     */
//    @Override
//    public FmBase queryById() {
//        return this.fmBaseDao.queryById();
//    }

    /**
     * 查询多条数据(分页查询)
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<FmBase> queryAllByLimit(int offset, int limit) {
        return this.fmBaseDao.queryAllByLimit(offset, limit);
    }


    /**
     * 通过实体作为筛选条件查询
     *
     * @param fmBase 实例对象
     * @return 对象列表
     */
    @Override
    public List<FmBase> getFmBaseAll(FmBase fmBase) {
        return this.fmBaseDao.getFmBaseAll(fmBase);
    }

    /**
     * 新增数据
     *
     * @param fmBase 实例对象
     * @return 实例对象
     */
    @Override
    public FmBase insert(FmBase fmBase) {
        this.fmBaseDao.insert(fmBase);
        return fmBase;
    }


    /**
     * 插入数据
     *
     * @param fmBase 实例对象
     * @return 实例对象
     */
    @Override
    public Boolean insertFmBaseDataOne(FmBase fmBase) {
        return null;
    }

    /**
     * 删除数据
     *
     * @param fmBase 实例对象
     * @return 实例对象
     */
    @Override
    public Boolean delFmBaseData(FmBase fmBase) {
        return this.fmBaseDao.delFmBaseData(fmBase) > 0;
    }

    /**
     * 插入数据
     *
     * @param fmBase 实例对象
     * @return 实例对象
     */
    @Override
    public Boolean updateFmBaseData(FmBase fmBase) {
        return this.fmBaseDao.updateFmBaseData(fmBase) > 0;
    }

    /**
     * @param formDefineId 表单定义ID
     * @param pageNo       页码
     * @param pageSize     页大小
     * @param condition    查询条件
     * @param orderBy      排序条件
     * @param flag         是否导出Excel
     * @param paramJson    动态SQL匹配参数
     * @param queryValue   模糊查询条件值
     * @return
     */
    @Override
    public JSONObject getLatestFormByDefine(String formDefineId, Integer pageNo, Integer pageSize, String condition, String orderBy,
                                            Boolean flag, String paramJson, String queryValue) throws BusinessException {
        // 查询表单是否存在
        FmBase formBase = fmBaseDao.getLatestFormByDefine(formDefineId);
        if (formBase == null) {
            throw new BusinessException("表单ID无效!");
        }

        JSONObject baseItemByFormId = this.getBaseItemByFormId(formBase.getId(), formBase.getPrimaryTable(), pageNo, pageSize, condition,
                orderBy, flag, paramJson, queryValue);

        return baseItemByFormId;
    }

    @Override
    public boolean delFmBaseToId(String colName, String value, String tableName) {


        return fmBaseDao.delFmBaseToId(colName, value, tableName) > 0;
    }

    @Override
    public boolean insertFmTableDate(String colNames, String values, String tableName) {


        return fmBaseDao.insertFmTableDate(colNames, values, tableName) > 0;
    }

    @Override
    public boolean updateFmTableDate(String colNames, String values, String tableName, String accordName, String accordValue) {
//        fmBaseDao.updateFmTableDate(colNames,values,tableName,accordName,accordValue)>0
        return true;
    }


    @Override
    public String deleteData(String businessIds, Long fromDefineId) {

        FmBase fmBase = fmBaseDao.queryById(fromDefineId);
        String tableName = fmBase.getPrimaryTable();
        List businessIdsList = Arrays.asList(businessIds.split(","));
        Integer integer = fmBaseDao.deleteData(businessIdsList, tableName);
        if (integer > 0) {
            return "删除成功！";
        } else {
            return "删除失败！";
        }
    }

    @Override
    public void submitBusinessStartFormData(String fromJson, Long fromDefineId) {
        RandomUtil randomUtil = new RandomUtil();
        boolean isPbid = false;

        Map<String, Object> props = JSON.parseObject(fromJson);
        FmBase fmBase = fmBaseDao.queryById(fromDefineId);
        Long businessId = Long.parseLong(randomUtil.generateNumberString(DataForTypeEnum.BUSINESS_ID));

        if (props.containsKey("BID")) {
            props.remove("BID");
        }

        if (!props.containsKey("PBID")) {
            isPbid = true;
        } else if (StringUtils.isBlank(((String) props.get("PBID")))) {
            isPbid = true;
            props.remove("PBID");
//            Long parentBusinessId = Long.parseLong(randomUtil.generateNumberString(DataForTypeEnum.PARENT_BUSINESS_ID));
//            props.put("PBID",parentBusinessId);
        }
        // 如果存在PBID
        this.saveFormData(props, fmBase, businessId, "insert", isPbid);

    }

    @Override
    public void submitBusinessFormData(String fromJson, Long fromDefineId, Long businessId) {
        boolean isPbid = false;
        Map<String, Object> props = JSON.parseObject(fromJson);
        FmBase fmBase = fmBaseDao.queryById(fromDefineId);
        this.saveFormData(props, fmBase, businessId, "update",isPbid);
    }

    /**
     * 保存数据的统一处理办法
     *
     * @param props
     * @param fmBase
     * @param businessId
     * @return
     */
    private String saveFormData(Map<String, Object> props, FmBase fmBase, Long businessId, String sqlType, boolean isPbid) {
        RandomUtil randomUtil = new RandomUtil();
            Long parentBusinessId = Long.parseLong(randomUtil.generateNumberString(DataForTypeEnum.PARENT_BUSINESS_ID));
        Long fromId = fmBase.getId();
        List<FmItem> fmItem = fmItemMapper.queryByFormId(fromId);
        String tableName = fmBase.getPrimaryTable();
        List<String> fieldNameList = new LinkedList<>();
        List<Object> valueList = new LinkedList<>();
        List<Object> updateList = new LinkedList<>();
        if (sqlType.equals("insert")) {
            fieldNameList.add("BID");
            valueList.add(businessId);
        }
        if(isPbid){
            fieldNameList.add("PBID");
            valueList.add(parentBusinessId);
        }
        //遍历

        for (Map.Entry<String, Object> entry : props.entrySet()) {
            if (entry.getValue() != null) {

                for (FmItem item : fmItem) {
                    String k = entry.getKey();
                    Object v = entry.getValue();
                    if (item.getColName().equals(k)) {
                        String colName = item.getColName();
                        fieldNameList.add(colName);
                        valueList.add("'" + v + "'");
                        if (sqlType.equals("update")) {
                            updateList.add(colName + "='" + v + "'");
                        }
                        break;
                    }
                }
            }
        }
        StringBuffer execSql = new StringBuffer();
        if (sqlType.equals("insert")) {
            execSql.append("insert into " + tableName + " (" + Joiner.on(",").join(fieldNameList) + " ) value " +
                    " (" + Joiner.on(",").join(valueList) + " )");

        } else {
            execSql.append("update  " + tableName + " set " + Joiner.on(",").join(updateList) + " where BID=" + businessId.toString());
        }
        this.fmBaseDao.dealData(execSql.toString());

        return null;

    }

    /**
     * @param fmItems      表头
     * @param formDefineId 表单定义ID
     * @param pageNo       页码
     * @param pageSize     页大小
     * @param condition    查询条件
     * @param orderBy      排序条件
     * @param flag         是否导出Excel
     * @param paramJson    动态SQL匹配参数
     * @param queryValue   模糊查询条件值
     * @return
     */
    //    @Override
    public List<Object> getFormBaseTable(List<FmItem> fmItems, Long formDefineId, String tableName, String condition, String orderBy,
                                         Boolean flag, String paramJson, String queryValue) throws BusinessException {
        List<Object> tableDateListObject = new ArrayList<>();
//        String collect = fmItems.stream().map(p ->  {if(p.getFieldType().equals("DATETIME")){
//            return  "date_format("+p.getTableName() + "." + p.getColName()+", '%Y-%m-%d') as " +p.getColName();
//        }else{
//
//               return p.getTableName() + "." + p.getColName();
//        }})
//                .collect(Collectors.joining(","));
//
//


        String collect = fmItems.stream().map(p ->p.getTableName() + "." + p.getColName())
                .collect(Collectors.joining(","));
        // 查出了数据
        List<JSONObject> tableDateToItem2 = new ArrayList<>();
        List<JSONObject> tableDateToItem = new ArrayList<>();
//pageNo != null && pageSize != null ? (pageNo - 1) * pageSize : null, pageSize,
        tableDateToItem = fmItemMapper.getTableDateToItem(collect, tableName, condition, orderBy,
                paramJson, queryValue);
//        for (JSONObject jsonObject : tableDateToItem2) {
//            JSONObject jsonObject1 = new JSONObject();
//            for (String s : jsonObject.keySet()) {
//
//                jsonObject1.put(s,    jsonObject.get(s).toString());
//            }
//            tableDateToItem.add(jsonObject1);
//        }

        // fmItems中含有所有的字段 整理查出的数据，把没个字段整理成TableDate的格式 （id，title，value colName，ColType,tableName）
        if (tableDateToItem.size() == 0) {
            return null;

        } else {
            for (JSONObject jsonObject : tableDateToItem) {
                List<TableDate> tableDateList = new ArrayList<>();
                JSONObject jsonObject1 = new JSONObject();

                for (FmItem fmItem : fmItems) {
//                    if (!StringUtils.isEmpty(jsonObject.get(fmItem.getColName()))) {

//                        TableDate tableDate = new TableDate();
                    jsonObject1.put(fmItem.getFieldName(), jsonObject.get(fmItem.getColName()));
//                        tableDate.setID(fmItem.getId());
//                        tableDate.setTitle(fmItem.getFieldAlias());
//                        tableDate.setValue(jsonObject.get(fmItem.getColName()));
//                        tableDate.setColName(fmItem.getColName());
//                        tableDate.setTableName(fmItem.getTableName());
//                        tableDate.setColType(fmItem.getFieldType());

//                    }
                }
                tableDateListObject.add(jsonObject1);
            }

        }
        return tableDateListObject;
    }


    /**
     * 查询虚拟表单
     *
     * @param formId     formId
     * @param tableName  表名
     * @param pageNo     页码
     * @param pageSize   页大小
     * @param condition  查询条件
     * @param orderBy    排序条件
     * @param flag       是否导出Excel
     * @param paramJson  动态SQL匹配参数
     * @param queryValue 模糊查询条件值
     * @param formId
     * @return
     */
    public JSONObject getBaseItemByFormId(Long formId, String tableName, Integer pageNo, Integer pageSize, String condition, String orderBy,
                                          Boolean flag, String paramJson, String queryValue) {
        List<FmItem> fmItems = fmItemMapper.queryByFormId(formId);

        if (fmItems.size() == 0) {
            throw new BusinessException("虚拟表单不存在!");
        }
        // TODO 此处可以用多线程处理，查询数据和处理表单并行处理，当两者处理完毕在一起返回
        // 此处准备好了表头 查询表头和下拉项
        this.perfectReturnItem(fmItems);
//        PageHelper.startPage(pageNo,pageSize);
//        page = PageHelper.startPage(pageNo,pageSize,true);
        Page<Object> pageInfo = PageHelper.startPage(pageNo == null ? 1 : pageNo, pageSize == null ? 10 : pageSize, true);
        List<Object> formBaseTable = this.getFormBaseTable(fmItems, formId, tableName, condition, orderBy, flag, paramJson, queryValue);
        JSONObject object = new JSONObject();
        object.put("fmData", formBaseTable == null ? new ArrayList<>() : formBaseTable);
        object.put("fields", fmItems == null ? new ArrayList<>() : fmItems);
        object.put("total", pageInfo.getTotal());
        return object;
    }


    /**
     * 完善返回项 字段下拉来源（1. 取字典，2.取RULE 4.此字段在提交前需要走反射做验证）
     *
     * @param fmItems
     */
    public void perfectReturnItem(List<FmItem> fmItems) {
        for (FmItem fmItem : fmItems) {
            if (fmItem.getMtFrom() != null) {
                switch (fmItem.getMtFrom()) {
                    case 1:
                        if (this.isKeyId(fmItem.getMtKey(), fmItem.getId())) {
                            List<KeyType> keyTypeToDictionary = fmItemMapper.getKeyTypeToDictionary(fmItem.getMtKey());
                            fmItem.setKeyTypeList(keyTypeToDictionary == null ? new ArrayList<>() : keyTypeToDictionary);
                        }
                        break;

                    case 2:
                        List<KeyType> ruleByIdToRuleExpress = this.getRuleByIdToRuleExpress(fmItem.getMtKey(), fmItem.getId());
                        fmItem.setKeyTypeList(ruleByIdToRuleExpress);
                        break;
                    case 3:
                        throw new BusinessException(fmItem.getId() + "项未配置MtFrom" +
                                "为3(在fm_item查id)");
                    case 4:
                        throw new BusinessException(fmItem.getId() + "配置的反射，此方法暂时为实现，具体查看FmBaseServiceImpl的perfectReturnItem中的代码");
                    case 5:
                        throw new BusinessException(fmItem.getId() + "项未配置MtFrom" +
                                "为3(在fm_item查id)");
                    default:
                        break;
                }
            }

        }
    }


    private Boolean isKeyId(String keyId, Long id) {
        if (id == null) {
            throw new BusinessException(keyId + "字典来源未配置");
        }
        return true;
    }

    /**
     * 通过规则表达式中去取值
     *
     * @param keyId
     * @return
     */
    private List<KeyType> getRuleByIdToRuleExpress(String keyId, Long id) {
        String ruleByIdToRuleExpress = fmItemMapper.getRuleByIdToRuleExpress(keyId);
        if (StringUtils.isEmpty(ruleByIdToRuleExpress)) {
            throw new BusinessException(id + "规则表达式为空或空字符串，请检查FM_ITEM表ID为" + id + "的数据");
        }
        List<KeyType> ruleExpress = fmItemMapper.getRuleExpress(ruleByIdToRuleExpress);
        return ruleExpress;
    }
}